%{
#include<ctype.h>
#include<stdio.h>
%}
%left '+' '-'
%left '*' '/'
%nonassoc UMINUS
%token NUM AND BASIC BREAK DO ELSE EQ FALSE GE VOID MAIN RETURN ADD2 SUB2
%token ID IF INDEX LE MINUS NE OR REAL TRUE WHILE KET
%token  RIGHT_BRA
%%


program : block { printf("program-->block\n"); }
	;
block : '{' decls stmts '}' { printf("block-->{decls stmts}\n"); }
	|type ID'('')'block { printf("block-->block\n"); }
	|type MAIN'('')'block { printf("block-->Main block\n"); }
	|
      ;
decls : decls decl { printf("decls-->decls decl\n"); }
      | /*empty*/
      ;

decl : type evaluates ';'{ printf("decl-->type evaluate_or_declare;\n"); }
     | evaluates';' { printf("decl-->evaluates;\n"); }
     | double_opt factor ';' { printf("decl-->double_opt factor;\n"); }
     | factor double_opt ';' { printf("decl-->factor double_opt;\n"); }
     | factor ';' { printf("decl-->factor;\n"); }

double_opt:ADD2 { printf("double_opt-->ADD2;\n"); }
	  |SUB2 { printf("double_opt-->SUB2;\n"); }
//      |type evaluate";"{printf("decl-->BASIC evaluates\n");}
     ;
stmts : stmts stmt { printf("stmts-->stmts stmt\n"); }
     | /*empty*/
     ;
stmt : DO stmt WHILE '(' bool ')' ';' { printf("stmt-->do stmt while(bool);\n"); }
     | IF '(' bool ')' stmt { printf("stmt--if(bool)stmt\n"); }
     | IF '(' bool ')' stmt ELSE stmt { printf("stmt-->if(bool)stmt else stmt\n"); }
     | WHILE '(' bool ')' stmt { printf("stmt-->while(bool)stmt\n"); }
     | BREAK ';' { printf("stmt-->break;\n"); }
     | block { printf("stmt-->block\n"); }
     | loc '=' bool ';' { printf("stmt-->loc=bool;\n"); }
     | loc '=' expr ';' { printf("stmt-->loc=expr;\n"); }
	|RETURN loc ';'{printf("stmts-->return loc\n");}
	|RETURN NUM ';'{printf("block-->return NUM\n");}
	|RETURN ';'{printf("block-->return\n");}
     ;
///evaluates : evaluates ',' evaluate_or_declare {printf("evaluates-->evaluates ',' evaluate_or_declare\n ");}
///	  | evaluate_or_declare {printf("evaluates-->evaluate_or_declare\n");}
/////移进规约冲突？？？
evaluates : evaluates evaluate_or_declare {printf("evaluates-->evaluates evaluate_or_declare\n ");}
	  | evaluate_or_declare {printf("evaluates-->evaluate_or_declare\n");}
	  | evaluate_or_declare ',' {printf("evaluates-->evaluate_or_declare,\n");}
	  ;

evaluate_or_declare : loc '=' NUM {printf("evaluate_or_declare-->ID=NUM\n");}
	  | loc '=' loc {printf("evaluate_or_declare-->ID=ID\n");}
	  | loc '=' expr {printf("evaluate_or_declare-->ID=expr\n");}
	  |loc{printf("evaluate_or_declare-->ID\n");}
	  ;

type : type '[' NUM ']' { printf("type-->type[num]\n"); }
     | BASIC { printf("type-->basic\n"); }
     | VOID { printf("type-->void\n"); }
     ;

loc : loc '[' bool ']' { printf("loc-->loc[bool]\n"); }
    | ID { printf("loc-->id\n");}
    ;
bool : bool OR join { printf("bool-->bool||join\n"); }
     | join { printf("bool-->join\n"); }
     ;
join : join AND equality { printf("join-->join&&equality\n"); }
     | equality { printf("join-->equality\n"); }
     ;
equality : equality EQ rel { printf("equality-->equality==rel\n"); }
         | equality NE rel { printf("equality-->equality!=rel\n"); }
         | rel { printf("equality-->rel\n"); }
         ;
rel : expr '<' expr { printf("rel-->expr<expr\n"); }
    | expr LE expr { printf("rel-->expr<=expr\n"); } 
    | expr GE expr { printf("rel-->expr>=expr\n"); }
    | expr '>' expr { printf("rel-->expr>expr\n"); }
    | expr { printf("rel-->expr\n"); }
    ;
expr : expr '+' term { printf("expr-->expr+term\n"); }
     | expr '-' term { printf("expr-->expr-term\n"); }  
     | term { printf("expr-->term\n"); }
     ;
term : term '*' unary { printf("term-->term*unary\n"); }
     | term '/' unary { printf("term-->term/unary\n"); }
     | unary { printf("term-->unary\n"); }
     ;
unary : '!' unary { printf("unary-->!unary\n"); }
      | '-' unary %prec UMINUS{ printf("unary-->-unary\n"); }
      | factor { printf("unary-->factor\n"); }
      ;
factor : '(' bool ')' { printf("factor-->(bool)\n"); }
       | loc { printf("factor-->loc\n"); }
       | NUM { printf("factor-->num\n"); }
       | REAL { printf("factor-->real\n"); }
       | TRUE { printf("factor-->true\n"); }
       | FALSE { printf("factor-->false\n"); }
       ;
       
%%
int  main()
{
 extern FILE *yyin;
 yyin=fopen("a.c","r");
 yyparse();
 return 0;
}
yyerror(char *s)
{
    printf("%s error!\n",s);
}
